#ifndef TESTTANGENT_H
#define TESTTANGENT_H

#include "TestScene.h"

class TestTangent:public TestScene{
public:
    void render(){
        mRenderer->render(mCamera);
    }

    void onKeyboard(unsigned char kc,int x,int y){
        vec3 t;
        vec3 r;
        float d=0;
        switch(kc){
        case 'w':
            t.y+=0.1f;
            break;
        case 's':
            t.y-=0.1f;
            break;
        case 'a':
            t.x-=0.1f;
            break;
        case 'd':
            t.x+=0.1f;
            break;
        case 'i':
            d+=1;
            r.x=1;
            break;
        case 'k':
            d-=1;
            r.x=1;
            break;
        case 'j':
            d-=1;
            r.y=1;
            break;
        case 'l':
            d+=1;
            r.y=1;
            break;
        }
        mCamera->translate(t,TS_PARENT);
    }
protected:

    void setupCamera(){
        mCamera=new Camera(mScene);
        mCamera->setFar(10);
        mCamera->setPosition(vec3(0,0,4),TS_PARENT);
        mRootNode->attachChild(mCamera);
        Viewport* vp=mCamera->getViewport();
        vp->mClearColor=vec4(0.1,0.2,0.3,1.0);
        vp->setRect(0,0,mWidth,mHeight);
    }

    void setupDisplay(){
        ShaderPtr simple(new Shader());
        simple->fromFile("glsl/simple.vs","glsl/simple.fs");
        MaterialPtr mat(new Material(simple));
        mat->setShininess(50.0);
        mat->setColor(vec4(1,0,0,1));

        SceneUtil ss;
        GeometryMap geos;
        ss.loadGeometries("media/teapot.obj",geos);
        GeometryPtr sphere=geos.begin()->second;
        sphere->updateTangent();

        MeshEntity* ent=new MeshEntity();
        ent->setGeometry(sphere);
        ent->setMaterial(mat);
        SceneNode* node=new SceneNode();
        node->attachEntity(ent);
        mRootNode->attachChild(node);

        VertexBufferPtr pBuf=sphere->getVertexBuffer("position");
        VertexBufferPtr tBuf=sphere->getVertexBuffer("tangent");
        VertexBufferPtr nBuf=sphere->getVertexBuffer("normal");
        IndexBufferPtr iBuf=sphere->getIndexBuffer();
        pBuf->getMirrorBuffer();
        uint32 indexNum=iBuf->getIndexNum();
        uint32* iData=(uint32*)iBuf->_lock(BA_READ);
        const vec3* pData=(const vec3*)pBuf->_lock(BA_READ);
        const vec3* tData=(const vec3*)tBuf->_lock(BA_READ);
        const vec3* nData=(const vec3*)nBuf->_lock(BA_READ);
        vec3* tanPos=new vec3[6*indexNum];
        vec4* tanColor=new vec4[6*indexNum];
        for(uint32 i=0;i<indexNum;i++){
            uint32 id=iData[i];
            const vec3& p=pData[id];
            const vec3& t=tData[id];
            const vec3& n=nData[id];
            vec3 b=glm::cross(t,n);

            uint32 s=i*6;
            //x
            tanPos[s]=p;
            tanPos[s+1]=p+t;
            tanColor[s]=vec4(1,0,0,1);
            tanColor[s+1]=vec4(1,0,0,1);
            //y
            tanPos[s+2]=p;
            tanPos[s+3]=p+n;
            tanColor[s+2]=vec4(0,1,0,1);
            tanColor[s+3]=vec4(0,1,0,1);
            //z
            tanPos[s+4]=p;
            tanPos[s+5]=p+b;
            tanColor[s+4]=vec4(0,0,1,1);
            tanColor[s+5]=vec4(0,0,1,1);
        }
        iBuf->_unlock();
        pBuf->_unlock();
        tBuf->_unlock();
        nBuf->_unlock();
        GeometryPtr tanGeo(new Geometry());
        VertexBufferPtr tanPBuf(new VertexBuffer(VA_POSITION,6*indexNum,BU_STATIC,tanPos));
        VertexBufferPtr tanCBuf(new VertexBuffer(VA_COLOR0,6*indexNum,BU_STATIC,tanColor));
        tanGeo->attachVertexBuffer("position",tanPBuf);
        tanGeo->attachVertexBuffer("color",tanCBuf);
    }
protected:
    Camera* mCamera;
    ShapeEntity* mTangents;
};

#endif